package web_api

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"net/http"
	"platon-tools/go-service/common/constant"
	"platon-tools/go-service/common/util"
	go_logger "platon-tools/go-service/go-logger"
	"platon-tools/go-service/module"
	"platon-tools/go-service/module/model"
	"strconv"
	"time"
)

type RoleListRequest struct {
	Params   string `form:"params" uri:"params" json:"params"`
	Page     int    `form:"page" uri:"page" json:"page" binding:"required"`
	PageSize int    `form:"page_size" uri:"page_size" json:"page_size" binding:"required"`
}

type RoleListResponse struct {
	Id             int            `json:"id"`
	RoleName       string         `json:"role_name"`
	MenuIds        []int          `json:"menu_ids"`
	AuthTree       []AuthTreeItem `json:"auth_tree"`
	Status         int            `json:"status"`
	CreateUserName string         `json:"create_user_name"`
	CreateTime     string         `json:"create_time"`
	UpdateUserName string         `json:"update_user_name"`
	UpdateTime     string         `json:"update_time"`
}

// 角色列表
func (api *HttpApi) RoleList(c *gin.Context) {

	var err error
	var result []*RoleListResponse

	pageStr := c.Query("page")
	pageSizeStr := c.Query("page_size")
	param := c.Query("params")

	page, err := strconv.Atoi(pageStr)
	if err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "page 应为数字"))
		return
	}

	pageSize, err := strconv.Atoi(pageSizeStr)
	if err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "pageSize 应为数字"))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var roles []*model.SysRole

		var count int
		var countDb = db.Table(model.SysRoleTable)
		if len(param) > 0 {
			countDb = countDb.Where("role_name like ?", "%"+param+"%")
		}
		err = countDb.Count(&count).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		if count > 0 {
			var sql string
			if len(param) > 0 {
				sql = "select * from sys_role where role_name like '%" + param + "%'"
			} else {
				sql = "select * from sys_role"
			}
			err = db.Table(model.SysRoleTable).Raw(sql).Order("update_time desc").Limit(pageSize).Offset((page - 1) * pageSize).Find(&roles).Error
			if err != nil {
				go_logger.Logger.Error(err.Error())
				c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
				return
			}
			for _, role := range roles {
				menuIds := role.GetMenuPerm()
				nodeIds := role.GetNodePerm()
				var nodes []*model.SysNode
				err = db.Table(model.SysNodeTable).Find(&nodes, nodeIds).Error
				if err != nil {
					go_logger.Logger.Error(err.Error())
					c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
					return
				}

				roleRes := &RoleListResponse{
					Id:             role.Id,
					RoleName:       role.RoleName,
					MenuIds:        menuIds,
					AuthTree:       BuildTree(nodes),
					Status:         role.Status,
					CreateUserName: role.CreateUserName,
					CreateTime:     role.CreateTime.Format(constant.DATE_FORMAT),
					UpdateUserName: role.UpdateUserName,
					UpdateTime:     role.UpdateTime.Format(constant.DATE_FORMAT),
				}
				result = append(result, roleRes)
			}
		}

		c.JSON(http.StatusOK, util.SuccessResponse(map[string]interface{}{
			"list":  result,
			"count": count,
		}))
		return
	}
}

// 角色详情
func (api *HttpApi) GetRole(c *gin.Context) {

	var err error

	roleIdStr := c.Query("role_id")

	roleId, err := strconv.Atoi(roleIdStr)
	if err != nil {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1003, "roleId 应为数字"))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var role model.SysRole
		err = db.Table(model.SysRoleTable).First(&role, roleId).Error
		if err != nil {
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1100, constant.ERROR_MESSAGE_1100))
			return
		}
		//menuMap := map[int]string{}
		menuIds := role.GetMenuPerm()
		//menuNames := []string{}
		//for _, menuId := range menuIds {
		//if v, ok := menuMap[menuId]; ok {
		//menuNames = append(menuNames, v)
		//continue
		//}
		//var menu model.SysMenu
		//err = db.Table(model.SysMenuTable).First(&menu, menuId).Error
		//if err != nil {
		//	go_logger.Logger.Error("获取菜单信息失败, menu_id: " + util.ToString(menuId))
		//	continue
		//}
		//menuNames = append(menuNames, menu.MenuName)
		//}

		var nodes []*model.SysNode
		err = db.Table(model.SysNodeTable).Find(&nodes, role.GetNodePerm()).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		authTree := BuildTree(nodes)

		roleRes := &RoleListResponse{
			Id:             role.Id,
			RoleName:       role.RoleName,
			MenuIds:        menuIds,
			AuthTree:       authTree,
			Status:         role.Status,
			CreateUserName: role.CreateUserName,
			CreateTime:     role.CreateTime.Format(constant.DATE_FORMAT),
			UpdateUserName: role.UpdateUserName,
			UpdateTime:     role.UpdateTime.Format(constant.DATE_FORMAT),
		}

		c.JSON(http.StatusOK, util.SuccessResponse(roleRes))
		return
	}
}

type AddRoleRequest struct {
	RoleName string `form:"role_name" json:"role_name" binding:"required"`
	MenuIds  []int  `form:"menu_ids" json:"menu_ids" binding:"required"`
	AuthTree string `form:"auth_tree" json:"auth_tree" binding:"required"`
}

// 新增角色
func (api *HttpApi) AddRole(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}
	userName, exist := c.Get("login_name")
	if !exist || userName == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	var param AddRoleRequest
	if err := c.ShouldBindJSON(&param); err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var role model.SysRole

		authTreeMap := map[string][]int{}
		err = json.Unmarshal([]byte(param.AuthTree), &authTreeMap)

		authTree := []int{}
		for _, v := range authTreeMap {
			authTree = append(authTree, v...)
		}

		menuPermByte, _ := json.Marshal(param.MenuIds)
		nodePermByte, _ := json.Marshal(authTree)

		role.RoleName = param.RoleName
		role.MenuPerm = string(menuPermByte)
		role.NodePerm = string(nodePermByte)
		role.RoleArea = "[]"
		role.Status = constant.USER_ROLE_USING
		role.CreateUserName = util.ToString(userName)
		role.CreateTime = time.Now()
		role.UpdateUserName = util.ToString(userName)
		role.UpdateTime = time.Now()

		err = db.Table(model.SysRoleTable).Save(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}

type EditRoleRequest struct {
	RoleId   int    `form:"role_id" json:"role_id" binding:"required"`
	Status   int    `form:"status" json:"status" binding:"required"`
	RoleName string `form:"role_name" json:"role_name" binding:"required"`
	MenuIds  []int  `form:"menu_ids" json:"menu_ids" binding:"required"`
	AuthTree string `form:"auth_tree" json:"auth_tree" binding:"required"`
}

// 编辑角色
func (api *HttpApi) EditRole(c *gin.Context) {

	var err error

	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}
	userName, exist := c.Get("login_name")
	if !exist || userName == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	var param EditRoleRequest
	if err := c.ShouldBindJSON(&param); err != nil {
		go_logger.Logger.Error(err.Error())
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
		return
	}

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var role model.SysRole
		where := map[string]interface{}{
			"id": param.RoleId,
		}
		err = db.Table(model.SysRoleTable).Where(where).First(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		authTreeMap := map[string][]int{}
		err = json.Unmarshal([]byte(param.AuthTree), &authTreeMap)

		authTree := []int{}
		for _, v := range authTreeMap {
			authTree = append(authTree, v...)
		}

		menuPermByte, _ := json.Marshal(param.MenuIds)
		nodePermByte, _ := json.Marshal(authTree)

		role.RoleName = param.RoleName
		role.MenuPerm = string(menuPermByte)
		role.NodePerm = string(nodePermByte)
		role.Status = param.Status
		role.UpdateUserName = util.ToString(userName)
		role.UpdateTime = time.Now()

		err = db.Table(model.SysRoleTable).Save(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}

// 删除角色
func (api *HttpApi) DeleteRole(c *gin.Context) {
	userId, exist := c.Get("login_id")
	if !exist || userId == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}
	userName, exist := c.Get("login_name")
	if !exist || userName == "" {
		c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1103, constant.ERROR_MESSAGE_1103))
		return
	}

	roleId := c.Query("role_id")

	r := api.service.ModuleByName("MYSQLDB")
	if db, ok := r.(*module.MysqlDB); ok {
		var role model.SysRole
		where := map[string]interface{}{
			"id":     roleId,
			"status": constant.USER_ROLE_USING,
		}
		err := db.Table(model.SysRoleTable).Where(where).First(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1001, constant.ERROR_MESSAGE_1001))
			return
		}

		role.Status = constant.USER_ROLE_DELETE
		role.UpdateTime = time.Now()
		role.UpdateUserName = util.ToString(userName)

		err = db.Table(model.SysRoleTable).Save(&role).Error
		if err != nil {
			go_logger.Logger.Error(err.Error())
			c.JSON(http.StatusOK, util.FailResponse(constant.ERROR_CODE_1002, constant.ERROR_MESSAGE_1002))
			return
		}

		c.JSON(http.StatusOK, util.SuccessResponse(nil))
		return
	}
}
